package com.neteast.androidclient.contact.util;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.neteast.androidclient.contact.Constant;
import com.neteast.androidclient.contact.activity.MainActivity;
import com.neteast.androidclient.contact.domain.Contact;
import com.neteast.androidclient.contact.domain.ContactData;

public class JsonUtil {
	
	/**
	 * 将Contact对象转换成json字符串
	 * 该方法用于新建contact对象时调用
	 * @return
	 * @throws JSONException 
	 */
	public static JSONObject translateContactToJson(Contact contact) throws JSONException {
		JSONObject object=null;
		if (contact==null) {
			return object;
		}
		object=new JSONObject();
		object.put("ownId", contact.ownId);
		object.put("displayName", contact.displayName);
		object.put("fphone", contact.fphone);
		object.put("femail", contact.femail);
		object.put("photo", contact.photo);
		object.put("hasPhoto", contact.hasPhoto?1:0);
		object.put("isReadOnly", 0);
		
		object.put("organization", contact.organization);
		object.put("job", contact.job);
		object.put("sortKey", Character.toString(contact.sortKey));
		object.put("remark", contact.remark);
		object.put("state", contact.state);
		int type=contact.isReadOnly?NetUtil.CLOUD:NetUtil.CONTACTS;
		parseGroupString2Json(contact.groups, object,type);
		if (!contact.phones.isEmpty()) {
			object.put("phones", parseContactData(contact.phones));
		}
		if (!contact.emails.isEmpty()) {
			object.put("emails", parseContactData(contact.emails));
		}
		if (!contact.ims.isEmpty()) {
			object.put("ims", parseContactData(contact.ims));
		}
		if (!contact.locations.isEmpty()) {
			object.put("locations", parseContactData(contact.locations));
		}
		return object;
	}
	/**
	 * 根据联系人的所属的分组名字符串，生成对应的json串
	 * @param groups
	 * @param object
	 * @throws JSONException
	 */
	private static void parseGroupString2Json(String groups, JSONObject object,int type)throws JSONException {
		if (groups!=null&&!groups.trim().equals("")) {
			JSONArray ga=new JSONArray();
			JSONObject obj;
			String[] gs = groups.split(",");
			for (int i = 0; i < gs.length; i++) {
				String groupName=gs[i];
				int groupId=NetUtil.getGroupIdByName(type, groupName);
				if (groupId==-1) {
					throw new RuntimeException("好友分组存储失败!");
				}
				obj=new JSONObject();
				obj.put("groupId", groupId);
				obj.put("groupName", groupName);
				obj.put("mimetypeId", Constant.MIME_GROUP);
				obj.put("modified", Constant.CONTACT_NEW);
				ga.put(obj);
			}
			object.put("groups", ga);
		}else {
			object.put("groups", "");
		}
	}
	/**
	 * 根据联系人的ContactData生成对应的json
	 * @param datas
	 * @return
	 * @throws JSONException
	 */
	private static JSONArray parseContactData(ArrayList<ContactData> datas)throws JSONException {
		JSONArray arr=new JSONArray();
		for (ContactData data : datas) {
			JSONObject obj=new JSONObject();
			obj.put("label", data.label);
			obj.put("content", data.content);
			obj.put("modified", Constant.CONTACT_NEW);
			obj.put("mimetypeId", data.mimeTypeId);
			arr.put(obj);
		}
		return arr;
	}
	/**
	 * 根据json生成ContactData
	 * @param datas
	 * @param array
	 * @param types
	 * @throws JSONException
	 */
	private static void populateContactData(ArrayList<ContactData> datas,
			JSONArray array,ArrayList<String> types) throws JSONException {
		if (array==null) {
			return;
		}
		int length = array.length();
		for(int i=0;i<length;i++){
			ContactData data=new ContactData();
			JSONObject obj = array.getJSONObject(i);
			data.id=obj.optInt("cid");
			data.label=obj.optString("label");
			if (!types.contains(data.label)) {
				types.add(data.label);
			}
			data.content=obj.optString("content");
			data.mimeTypeId=obj.getInt("mimetypeId");
			data.modified=Constant.CONTACT_NOCHANGE;
			datas.add(data);
		}
		Collections.sort(datas);
	}

	/**
	 * 解析联系人列表的json
	 * @param context
	 * @param in
	 * @return
	 * @throws Exception
	 */
	public static ArrayList<Contact> parseContacts(Context context,InputStream in) throws Exception {
		byte[] data = getDataFromInputStream(in);
		if (data != null && data.length > 0) {
			String json = new String(data, "UTF-8");
			Log.i("test", "json="+json);
			if (json.trim().equals("null")) {
				throw new RuntimeException("用户列表为空");
			}
			if (json.trim().startsWith("{\"code\"")) { 
				JSONObject obj = new JSONObject(json);
				switch (obj.optInt("code")) {
				case 1:
					break;
				default:
					throw new RuntimeException(obj.optString("description"));
				}
			}
			if (json.trim().startsWith("[{\"contactId\":")) {
				JSONArray array = new JSONArray(json);
				ArrayList<Contact> contacts = new ArrayList<Contact>();
				int length = array.length();
				for (int i = 0; i < length; i++) {
					Contact contact = new Contact();
					JSONObject obj = array.getJSONObject(i);
					contact.ownId = LoginUtil.getLastLoginUserId(context);
					contact.contactId = obj.optInt("contactId");
					contact.displayName = obj.optString("displayName");
					contact.isReadOnly = obj.optInt("isReadOnly") == 1 ? true: false;
					contact.sortKey = Character.toUpperCase(obj.optString("sortKey").charAt(0));
					contact.photo = obj.optString("photo");
					contact.hasPhoto = obj.optInt("hasPhoto") == 1 ? true: false;
					contact.fphone = obj.optString("fphone");
					contact.femail = obj.optString("femail");
					contact.organization = obj.optString("organization");
					contact.job = obj.optString("job");
					parseGroupJson2String(contact, obj);
					contacts.add(contact);
				}
				return contacts;
			}
		}
		return null;
	}
	/**
	 * 从输入流获取数据
	 * @param inputStream
	 * @return
	 * @throws Exception
	 */
	public static byte[] getDataFromInputStream(InputStream inputStream) throws Exception {
		ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
		int len=0;
		byte[] buffer=new byte[1024];
		while ((len=inputStream.read(buffer))>0) {
			outputStream.write(buffer, 0, len);
		}
		inputStream.close();
		return outputStream.toByteArray();
	}
	/**
	 * 解析联系人的详细信息
	 * @param context
	 * @param inputStream
	 * @return
	 * @throws Exception
	 */
	public static Contact parseContact(Context context,InputStream inputStream) throws Exception {
		byte[] data = getDataFromInputStream(inputStream);
		if (data!=null&&data.length>0) {
			String json=new String(data, "UTF-8");
			Log.i("test", "json="+json);
			if (json.trim().startsWith("{\"code\"")) {
				JSONObject obj=new JSONObject(json);
				switch (obj.optInt("code")) {
				case 1:
					break;
				default:
					throw new RuntimeException(obj.optString("description"));
				}
			}
			if (json.trim().startsWith("{\"contactId\":")) {
				Contact contact=new Contact();
				JSONObject obj=new JSONObject(json);
				contact.ownId=LoginUtil.getLastLoginUserId(context);
				contact.contactId=obj.optInt("contactId");
				contact.displayName=obj.optString("displayName");
				contact.fphone=obj.optString("fphone");
				contact.femail=obj.optString("femail");
//				contact.sortKey=Character.toUpperCase(PinYinUtil.getSortKey(contact.displayName));
				contact.sortKey=Character.toUpperCase(obj.optString("sortKey").charAt(0));
				contact.isReadOnly=obj.optInt("isReadOnly")==1?true:false;
				contact.photo=obj.getString("photo");
				contact.hasPhoto=obj.optInt("hasPhoto")==1?true:false;
				
				contact.organization=obj.optString("organization");
				contact.job=obj.optString("job");
				contact.remark=obj.optString("remark");
//				contact.state=obj.optString("state");
				populateContactData(contact.phones,obj.optJSONArray("phones"),MainActivity.phoneTypes);
				populateContactData(contact.emails,obj.optJSONArray("emails"),MainActivity.emailTypes);
				populateContactData(contact.ims,obj.optJSONArray("ims"),MainActivity.imTypes);
				populateContactData(contact.locations,obj.optJSONArray("locations"),MainActivity.locationTypes);
				parseGroupJson2String(contact, obj);
				return contact;
			}
		}
		return null;
	}
	
	public static boolean parseBasePostResponse(Context context,InputStream inputStream) throws Exception{
		byte[] data = getDataFromInputStream(inputStream);
		if (data!=null&&data.length>0) {
			String json=new String(data, "UTF-8");
			Log.i("test", "json="+json);
			if (json.trim().startsWith("{\"code\"")) {
				JSONObject obj=new JSONObject(json);
				switch (obj.optInt("code")) {
				case 1:
					return true;
				default:
					throw new RuntimeException(obj.optString("description"));
				}
			}
		}
		return false;
	}
	/**
	 * 解析分组的json组拼成分组名字符串，用逗号分隔
	 * @param contact
	 * @param obj
	 * @throws JSONException
	 */
	private static void parseGroupJson2String(Contact contact, JSONObject obj)throws JSONException {
		JSONArray ga = obj.optJSONArray("groups");
		if (ga!=null) {
			int size=ga.length();
			StringBuilder sb=new StringBuilder();
			for(int i=0;i<size;i++){
				JSONObject o = ga.getJSONObject(i);
				sb.append(o.optString("groupName")).append(",");
			}
			if (sb.length()>0) {
				sb.deleteCharAt(sb.length()-1);
			}
			contact.groups=sb.toString();
		}
	}
	/**
	 * 解析分组信息，将分组名装入ArrayList返回，将分组id和分组名的映射关系装入map
	 * @param context
	 * @param in
	 * @param map
	 * @return
	 * @throws Exception
	 */
	public static ArrayList<String> parseGroups(Context context,InputStream in, HashMap<String, Integer> map) throws Exception {
		byte[] data = getDataFromInputStream(in);
		if (data!=null&&data.length>0) {
			String json=new String(data,"UTF-8");
			Log.i("test", "json="+json);
			if (json.trim().startsWith("{\"code\"")) {
				JSONObject obj=new JSONObject(json);
				switch (obj.optInt("code")) {
				case 1:
					break;
				default:
					throw new RuntimeException(obj.optString("description"));
				}
			}
			if (json.trim().startsWith("[{\"groupId\"")) {
				ArrayList<String> list=new ArrayList<String>();
				JSONArray array=new JSONArray(json);
				int length = array.length();
				for (int i = 0; i < length; i++) {
					JSONObject obj = array.getJSONObject(i);
					int id=obj.optInt("groupId");
					String groupName=obj.optString("groupName");
					list.add(groupName);
					map.put(groupName, id);
				}
				return list;
			}
			return null;
		}else {
			throw new RuntimeException("获取分组信息失败");
		}
	}
	/**
	 * 判断联系人是否发生改变 若发生改变，则将改变的部分组拼成json串
	 * @param cold
	 * @param cNew
	 * @return
	 */
	public static JSONObject isContactChanged(Contact cold,Contact cNew){
		try {
			Log.i("test", "old="+cold);
			Log.i("test", "new="+cNew);
			boolean isChanged=false;
			JSONObject object=new JSONObject();
			object.put("ownId", cold.ownId);
			object.put("contactId", cold.contactId);
			
			if (cold.isReadOnly&&cold.ownId!=cold.contactId) {
			}else {
				if (!isEqual(cold.displayName, cNew.displayName)) {
					isChanged=true;
					object.put("displayName", cNew.displayName);
				}
				if (cNew.sortKey!=cold.sortKey) {
					isChanged=true;
					object.put("sortKey", Character.toString(cNew.sortKey));
				}
				if (!isEqual(cold.fphone, cNew.fphone)) {
					isChanged=true;
					object.put("fphone", cNew.fphone);
				}
				if (!isEqual(cold.femail, cNew.femail)) {
					isChanged=true;
					object.put("femail", cNew.femail);
				}
				if (!isEqual(cold.photo, cNew.photo)) {
					isChanged=true;
					object.put("photo", cNew.photo);
				}
				if (cNew.hasPhoto!=cold.hasPhoto) {
					isChanged=true;
					object.put("hasPhoto", cNew.hasPhoto?1:0);
				}
			}
			
			if (!isEqual(cold.organization, cNew.organization)) {
				isChanged=true;
				object.put("organization", cNew.organization);
			}
			
			if (!isEqual(cold.job, cNew.job)) {
				isChanged=true;
				object.put("job", cNew.job);
			}
			
			if (!isEqual(cold.groups, cNew.groups)) {
				isChanged=true;
				int type=cNew.isReadOnly?NetUtil.CLOUD:NetUtil.CONTACTS;
				parseGroupString2Json(cNew.groups, object, type);
			}
			
			if (!isEqual(cold.remark, cNew.remark)) {
				isChanged=true;
				object.put("remark", cNew.remark);
			}
			
//			if (!cNew.state.equals(cold.state)) {
//				isChanged=true;
//				object.put("state", cNew.state);
//			}
			
			JSONArray array = compareContactData(cold.phones, cNew.phones);
			if (array.length()>0) {
				isChanged=true;
				object.put("phones", array);
			}
			array = compareContactData(cold.emails, cNew.emails);
			if (array.length()>0) {
				isChanged=true;
				object.put("emails", array);
			}
			array = compareContactData(cold.ims, cNew.ims);
			if (array.length()>0) {
				isChanged=true;
				object.put("ims", array);
			}
			array = compareContactData(cold.locations, cNew.locations);
			if (array.length()>0) {
				isChanged=true;
				object.put("locations", array);
			}
			if (isChanged) {
				return object;
			}
		} catch (Exception e) {
			Log.e("test", e.getMessage(),e);
		}
		return null;
	}
	/**
	 * 比较ContactData是否发生改变，若是，则将改变的数据组拼成json
	 * @param oldPhones
	 * @param newPhones
	 * @return
	 * @throws JSONException
	 */
	private static JSONArray compareContactData(ArrayList<ContactData> oldPhones, 
			ArrayList<ContactData> newPhones)throws JSONException {
		JSONArray array=new JSONArray();
		JSONObject jsonObject;
		int countI=oldPhones.size();
		int countJ=newPhones.size();
		int i=0;
		int j=0;
		for (;i<countI&&j<countJ; i++,j++) {
			ContactData oldData = oldPhones.get(i);
			ContactData newData = newPhones.get(j);
			if (!oldData.equals(newData)) {
				jsonObject=new JSONObject();
				jsonObject.put("cid", oldData.id);
				jsonObject.put("label", newData.label);
				jsonObject.put("content", newData.content);
				jsonObject.put("modified", Constant.CONTACT_UPDATE);
				jsonObject.put("mimetypeId", newData.mimeTypeId);
				array.put(jsonObject);
			}
		}
		if (countI<countJ) {
			for (;j<countJ;j++){
				jsonObject=new JSONObject();
				ContactData data = newPhones.get(j);
				jsonObject.put("label", data.label);
				jsonObject.put("content", data.content);
				jsonObject.put("modified", Constant.CONTACT_NEW);
				jsonObject.put("mimetypeId", data.mimeTypeId);
				array.put(jsonObject);
			}
		}else if (countI>countJ) {
			for (;i<countI;i++){
				jsonObject=new JSONObject();
				ContactData data = oldPhones.get(i);
				jsonObject.put("cid", data.id);
				jsonObject.put("modified", Constant.CONTACT_DELETE);
				jsonObject.put("mimeTypeId", data.mimeTypeId);
				array.put(jsonObject);
			}
		}
		return array;
	}
	/**
	 * 判断两个字符串是否相等
	 * @param s1
	 * @param s2
	 * @return
	 */
	private static boolean isEqual(String s1,String s2) {
		if (TextUtils.isEmpty(s1)&&TextUtils.isEmpty(s2)) {
			return true;
		}
		return s2.equals(s1);
	}
	/**
	 * 将联系人的分组信息改变生成json串
	 * @param contact
	 * @return
	 * @throws Exception
	 */
	public static JSONObject updateContactGroup(Contact contact) throws Exception {
		JSONObject obj=new JSONObject();
		obj.put("ownId", contact.ownId);
		obj.put("contactId", contact.contactId);
		int type=contact.isReadOnly?NetUtil.CLOUD:NetUtil.CONTACTS;
		parseGroupString2Json(contact.groups, obj,type);
		return obj;
	}
	/**
	 * 生成更新头像的json
	 * @param contact
	 * @return
	 */
	public static JSONObject updatePhoto(Contact contact) {
		JSONObject obj = new JSONObject();
		try {
			obj.put("ownId", contact.ownId);
			obj.put("contactId", contact.contactId);
			obj.put("photo", contact.photo);
			obj.put("hasPhoto", 1);
			Log.i("test", obj.toString());
			return obj;
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return null;
	}
	public static JSONObject updateContactGroup(Contact contact, String oldGroup) throws Exception {
		if (TextUtils.isEmpty(oldGroup)) {
			return updateContactGroup(contact);
		}
		if (!TextUtils.isEmpty(oldGroup)&&TextUtils.isEmpty(contact.groups)) {
			return null;
		}
		String[] olds = oldGroup.split(",");
		String[] news = contact.groups.split(",");
		int temp;
		temp=olds.length>news.length?news.length:olds.length;
		for(int i=0;i<temp;i++){
			
		}
		return null;
	}
}
